#include "stdafx.h"
#include "HXUtil.h"

//-----------------------------------------------------------------------------

HXStopWatch::HXStopWatch(){
    timer.start.QuadPart=0;
    timer.stop.QuadPart=0;
    QueryPerformanceFrequency( &frequency ) ;
}

void HXStopWatch::startTimer( ) {
    QueryPerformanceCounter(&timer.start) ;
}

void HXStopWatch::stopTimer( ) {
    QueryPerformanceCounter(&timer.stop) ;
}

double HXStopWatch::getElapsedTime() {
    LARGE_INTEGER time;
    time.QuadPart = timer.stop.QuadPart - timer.start.QuadPart;
    return LIToSecs( time) ;
}

float HXStopWatch::getElapsedTimeF() {
    LARGE_INTEGER time;
    time.QuadPart = timer.stop.QuadPart - timer.start.QuadPart;
    return LIToSecsF(time) ;
}

double HXStopWatch::LIToSecs(LARGE_INTEGER & L) {
    return ((double)L.QuadPart /(double)frequency.QuadPart) ;
}

float HXStopWatch::LIToSecsF(LARGE_INTEGER & L) {
    return ((float)L.QuadPart /(float)frequency.QuadPart) ;
}

//-----------------------------------------------------------------------------

//! Shows a given message in a dialogue box.
void ANotify(HWND hwnd, const char* a_Text, ...)
{
    char szBuffer[1024];

    // Format the input string
    va_list pArgs;
    va_start(pArgs, a_Text);

	StringCchVPrintfA(szBuffer, 1023, a_Text, pArgs);
	
    va_end(pArgs);

    // Ensure that the formatted string is NULL-terminated
    szBuffer[1023] = '\0';

	// Display in window
    MessageBoxA(hwnd, szBuffer, "HXPlayer", MB_OK | MB_ICONERROR);
}

//! Shows a given message in a dialogue box (wide character version).
void WNotify(HWND hwnd, const wchar_t* a_Text, ...)
{
    wchar_t szBuffer[1024];

    // Format the input string
    va_list pArgs;
    va_start(pArgs, a_Text);

	StringCchVPrintfW(szBuffer, 1023, a_Text, pArgs);
	
    va_end(pArgs);

    // Ensure that the formatted string is NULL-terminated
    szBuffer[1023] = L'\0';

	// Display in window
	MessageBox(hwnd, szBuffer, L"Head X", MB_OK | MB_ICONERROR);
}


//! Generate a unique filename in the temporary directory
wstring GetTemporaryFile(LPCTSTR lpPrefixString)
{

	DWORD dwRetVal;
	DWORD dwBufSize=MAX_PATH;
	TCHAR lpPathBuffer[MAX_PATH];
	UINT uRetVal;
    wchar_t szTempName[MAX_PATH];  



    // Get the temp path.
    dwRetVal = GetTempPath(dwBufSize,     // length of the buffer
                           lpPathBuffer); // buffer for path 
    if (dwRetVal > dwBufSize || (dwRetVal == 0))
    {
		/*
        printf ("GetTempPath failed with error %d.\n", 
                GetLastError());
				*/
        return NULL;
    }

    // Create a temporary file. 
    uRetVal = GetTempFileName(lpPathBuffer, // directory for tmp files
                              lpPrefixString,  // temp file name prefix 
                              0,            // create unique name 
                              szTempName);  // buffer for name 
    if (uRetVal == 0)
    {
		/*
        printf ("GetTempFileName failed with error %d.\n", 
               GetLastError());
	     */
        return NULL;
    }

	return wstring(szTempName);



}

bool IsOSXPOrLater()
{
	OSVERSIONINFO osvi;
    bool bIsWindowsXPorLater;

    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

    GetVersionEx(&osvi);

    bIsWindowsXPorLater = 
       ( (osvi.dwMajorVersion > 5) ||
       ( (osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion >= 1) ));

	return bIsWindowsXPorLater;
}

bool IsOSVistaOrLater()
{
	OSVERSIONINFO osvi;
    bool bIsWindowsXPorLater;

    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

    GetVersionEx(&osvi);

    bIsWindowsXPorLater = (osvi.dwMajorVersion >= 6);

	return bIsWindowsXPorLater;
}

//! Converts 8-bit character string to wide 16-bit character string.
wstring StringToWString(const string& a_String)
{
	vector<wchar_t> widevec(a_String.length()+1);
	size_t converted = 0;
	mbstowcs_s(&converted, &widevec[0], widevec.size(), a_String.c_str(), _TRUNCATE);
	if (converted)
	{
		return &widevec[0];
	}
	else
	{
		return wstring();
	}
}

//! Converts wide 16-bit character string to 8-bit character string.
string WStringToString(const wstring& a_String)
{
	vector<char> narrowvec(a_String.length()+4);
	size_t converted = 0;
	wcstombs_s(&converted, &narrowvec[0], narrowvec.size(), a_String.c_str(), _TRUNCATE);
	if (converted)
	{
		return &narrowvec[0];
	}
	else
	{
		return string();
	}
}

float WStringToFloat(const wstring& a_String)
{
    wstringstream converter;
    float value = 0;
                        
    converter.precision(10);
    converter.fill('0');
    converter.setf( ios::fixed, ios::floatfield );                              
                        
    converter << a_String;
    converter >> value;
    return value;
}

int WStringToInt(const wstring& a_String)
{
	return atoi(WStringToString(a_String).c_str());
}

bool WStringToBool(const wstring& a_String)
{
	if ((a_String == L"yes") ||
		(a_String == L"Yes") ||
		(a_String == L"YES") ||
		(a_String == L"true") ||
		(a_String == L"True") ||
		(a_String == L"TRUE") ||
		(a_String == L"on") ||
		(a_String == L"On") ||
		(a_String == L"ON") ||
		(a_String == L"y") ||
		(a_String == L"Y") ||
		(a_String == L"1")
	   )
	{
		return true;
	}
	return false;
}

HXBlendMode WStringToBlendMode(const wstring& a_String)
{
	wstring lowString = WStringToLowerCase(a_String);
	if (lowString.size())
	{
		if (lowString == L"sine")
		{
			return HXBM_SIN;
		}
		else
		if (lowString == L"linear")
		{
			return HXBM_LINEAR;
		}
		else
		if (lowString == L"sinc")
		{
			return HXBM_SINC;
		}
		else
		if ((lowString == L"halfsine") || (lowString == L"half-sine"))
		{
			return HXBM_HSIN;
		}
		else
		if ((lowString == L"inverse halfsine") || (lowString == L"inverse half-sine"))
		{
			return HXBM_IHSIN;
		}
		else
		if (lowString == L"square")
		{
			return HXBM_SQR;
		}
		else
		if (lowString == L"root")
		{
			return HXBM_ROOT;
		}
		else
		if (lowString == L"inverse square")
		{
			return HXBM_ISQR;
		}
		else
		if (lowString == L"inverse root")
		{
			return HXBM_IROOT;
		}
		else
		if (lowString == L"max")
		{
			return HXBM_MAX;
		}
	}
	return HXBM_ANYBLEND;
}

wstring WStringToLowerCase(const wstring& a_String)
{
	wstring lowstring;
	for (size_t i = 0; i < a_String.size(); i++)
	{
		lowstring.push_back(towlower(a_String[i]));
	}
	return lowstring;
}

//-----------------------------------------------------------------------------


float TransformRoot(float position)
{
	return sqrt(position);
}

double TransformRoot(double position)
{
	return sqrt(position);
}

float TransformSqr(float position)
{
	return position*position;
}

double TransformSqr(double position)
{
	return position*position;
}

float TransformHalfSin(float position)
{
	return static_cast<float>(TransformHalfSin(static_cast<double>(position)));
}

double TransformHalfSin(double position)
{
	return sin(position*PI/2);
}

float TransformInvRoot(float position)
{
	return 1-TransformRoot(1-position);
}

double TransformInvRoot(double position)
{
	return 1-TransformRoot(1-position);
}

float TransformInvSqr(float position)
{
	return 1-TransformSqr(1-position);
}

double TransformInvSqr(double position)
{
	return 1-TransformSqr(1-position);
}

float TransformInvHalfSin(float position)
{
	return 1-TransformHalfSin(1-position);
}

double TransformInvHalfSin(double position)
{
	return 1-TransformHalfSin(1-position);
}

float TransformSin(float position)
{
	return static_cast<float>(TransformSin(static_cast<double>(position)));
}

double TransformSin(double position)
{
	return (sin((position-0.5f)*PI)+1)/2;
}

float TransformSinc(float position)
{
	return static_cast<float>(TransformSinc(static_cast<double>(position)));
}

double TransformSinc(double position)
{
	if (position != 1.0)
	{
		return sin((2*(position-1))*PI)/((2*(position-1))*PI);
	}
	else	
	{
		return 1.0;
	}
}

//-----------------------------------------------------------------------------